package openase.audiosearch.job;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;

import openase.audiosearch.comm.CommUtil;
import openase.audiosearch.comm.request.Request;
import openase.audiosearch.comm.request.decoder.facade.RequestDecoderFacade;
import openase.audiosearch.comm.response.Response;
import openase.audiosearch.comm.response.encoder.facade.ResponseEncoderFacade;
import openase.audiosearch.processor.RequestProcessorFacade;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class RequestJob extends Job {

	private static final Log logger = LogFactory.getLog(RequestJob.class);

	public RequestJob(SelectionKey key) {
		super(key);
	}

	public void run() {
		SelectionKey key = key();
		SocketChannel channel = (SocketChannel) key.channel();

		try {
			long ini = now();
			
			long ini_read = now();
			ByteBuffer inputBuffer = CommUtil.recv(channel);
			long end_read = now();
			logger.info(String.format("Reading buffer for next request took %dms", (end_read - ini_read)));

			Request request = RequestDecoderFacade.decode(inputBuffer);

			logger.info(String.format("%s requested %s", channel, request));

			long ini_process = now();
			Response response = RequestProcessorFacade.process(request);
			long end_process = now();

			logger.info(String.format("Request %s generated response %s for %s. Process took %dms", request, response, channel, end_process - ini_process));

			ByteBuffer outputBuffer = ResponseEncoderFacade.encode(response);

			long ini_send = now();
			CommUtil.send(channel, outputBuffer);
			long end_send = now();
			logger.info(String.format("Sending buffer for response took %dms", (end_send - ini_send)));

			long end = now();

			logger.info(String.format("The total request process took %dms", (end - ini)));
		} catch (IOException ioe) {
			logger.error("An I/O erro occurred while processing request.", ioe);
			IOUtils.closeQuietly(channel);
		}
	}

	private static long now() {
		return System.currentTimeMillis();
	}
}
